#include "../StdInc.h"

namespace GSTrader
{
	namespace TradeBase
	{
		CSubscribeInstrument::CSubscribeInstrument() : m_strMainMarketID(""), m_strMainInstrument("")
		{

		}

		CSubscribeInstrument::~CSubscribeInstrument()
		{

		}

		CSubscribeInstrument::CSubscribeInstrument(mapMarketSubscribe& mapIns): m_strMainMarketID(""), m_strMainInstrument("")
		{
			m_mapInstrument = mapIns;
		}

		void CSubscribeInstrument::RemoveAll()
		{

		}

		int CSubscribeInstrument::GetCount()
		{
			int nCount = 0;

			for (auto it : m_mapInstrument)
			{
				nCount += it.second.size();
			}

			return nCount;
		}

		bool CSubscribeInstrument::Contains(string strInstrumentID, string strExchangeID)
		{
			if (strInstrumentID.empty() || strExchangeID.empty())
				return false;

			map<string, vector<string>>::iterator it = m_mapInstrument.find(strExchangeID);
			if (it != m_mapInstrument.end())
			{
				vector<string>::iterator itStr = find(it->second.begin(), it->second.end(), strInstrumentID);
				if (itStr != it->second.end())
					return true;
			}

			return false;
		}

		CSubscribeInstrument::CSubscribeInstrument(vector<CInstrumentLongCode>& vInstrumentCode)
		{
			for (size_t x = 0; x < vInstrumentCode.size(); x++)
			{
				CInstrumentLongCode& longCode = vInstrumentCode[x];
				if (longCode.m_strExchangeId.empty())
				{
					assert(false);
					continue;
				}

				map<string, vector<string>>::iterator it = m_mapInstrument.find(longCode.m_strExchangeId);
				if (it != m_mapInstrument.end())
				{
					it->second.push_back(longCode.m_strInstrumentId);
				}
				else
				{
					m_mapInstrument[longCode.m_strExchangeId] = vector<string>();
					m_mapInstrument[longCode.m_strExchangeId].push_back(longCode.m_strInstrumentId);
				}

			}
		}

		CSubscribeInstrument::CSubscribeInstrument(vector<CInstrument*>& vInstrument)
			: m_strMainMarketID(""), m_strMainInstrument("")
		{
			for (auto p : vInstrument)
			{
				map<string, vector<string>>::iterator it = m_mapInstrument.find(p->m_strExchangeID);
				if (it != m_mapInstrument.end())
				{
					it->second.push_back(p->m_strSymbol);
				}
				else
				{
					m_mapInstrument[p->m_strExchangeID] = vector<string>();
					m_mapInstrument[p->m_strExchangeID].push_back(p->m_strSymbol);
				}
			}
		}

		void AddDataToSubscribe(mapMarketSubscribe& mapIns, string strExchangeID, vector<string>& vInstrumentID)
		{
			if (!strExchangeID.empty() && !vInstrumentID.empty())
			{
				map<string, vector<string>>::iterator it = mapIns.find(strExchangeID);
				if (it == mapIns.end())
				{
					mapIns[strExchangeID] = vector<string>();
					it = mapIns.find(strExchangeID);
				}

				for (auto str : vInstrumentID)
				{
					if (str.empty())
						continue;

					auto itStr = find(it->second.begin(), it->second.end(), str);
					if (itStr == it->second.end())
					{
						it->second.push_back(str);
					}
				}
			}
		}

		void CSubscribeInstrument::AddSubscribe(CInstrument* pInstrument)
		{
			if (pInstrument == NULL)
				return;

			vector<string> vSubscript;
			vSubscript.push_back(pInstrument->m_strSymbol);
			AddDataToSubscribe(m_mapInstrument, pInstrument->m_strExchangeID, vSubscript);
		}

		void CSubscribeInstrument::AddSubscribe(CInstrumentLongCode& longCode)
		{
			if (!longCode.IsValid())
				return;

			vector<string> vSubscript;
			vSubscript.push_back(longCode.m_strInstrumentId);

			AddDataToSubscribe(m_mapInstrument, longCode.m_strExchangeId, vSubscript);
		}

		void CSubscribeInstrument::AddToSubscribe(mapMarketSubscribe& mapIns)
		{
			for (auto it : m_mapInstrument)
			{
				AddDataToSubscribe(mapIns, it.first, it.second);
			}
		}

		void CSubscribeInstrument::AddSubscribe(CSubscribeInstrument* pSubscribe)
		{
			if (pSubscribe == NULL)
				return;

			pSubscribe->AddToSubscribe(m_mapInstrument);
		}

		void CSubscribeInstrument::UnSubscribe(CSubscribeInstrument* pSubscribe)
		{
			if (pSubscribe == NULL)
				return;

			for (auto it : pSubscribe->m_mapInstrument)
			{
				string strExchange = it.first;
				auto it2 = m_mapInstrument.find(strExchange);
				if (it2 != m_mapInstrument.end())
				{
					vector<string>& vIns = it2->second;
					for (auto x : it.second)
					{
						auto itStr = find(vIns.begin(), vIns.end(), x);
						if (itStr != vIns.end())
						{
							vIns.erase(itStr);
						}
					}
				}
			}
		}

		void CSubscribeInstrument::GetSubscribe(vector<string>& vSubscript)
		{
			vSubscript.clear();
			if (!m_strMainInstrument.empty())
			{
				vSubscript.push_back(m_strMainInstrument);
			}

			for (auto it : m_mapInstrument)
			{
				for (string str : it.second)
				{
					if (!str.empty())
					{
						vSubscript.push_back(str);
					}
				}
			}
		}

		void CSubscribeInstrument::GetSubscribeLongCode(vector<CInstrumentLongCode>& vLongCode)
		{
			vLongCode.clear();
			if (!m_strMainInstrument.empty())
			{
				vLongCode.push_back(CInstrumentLongCode(m_strMainInstrument, m_strMainMarketID));
			}

			for (auto it : m_mapInstrument)
			{
				for (string str : it.second)
				{
					if (!str.empty())
					{
						vLongCode.push_back(CInstrumentLongCode(str, it.first));
					}
				}
			}
		}

		bool CSubscribeInstrument::Remove(CInstrumentLongCode& longCode)
		{
			if (!longCode.IsValid())
				return false;

			auto it = m_mapInstrument.find(longCode.m_strExchangeId);
			if (it != m_mapInstrument.end())
			{
				vector<string>& vIns = it->second;
				vIns.erase(find(vIns.begin(), vIns.end(), longCode.m_strInstrumentId));

				return true;
			}

			return false;
		}
	}
}